#ifndef BLOCKING_QUEUE_CORE_H_
#define BLOCKING_QUEUE_CORE_H_

#include "Queue.hh"

//
/**
 * \file BlockingQueueCore.hh
 * \author  jsk <jsk.jinsubkim@gmail.com>
 * \version 1.0
 *
 * \class BlockingQueueCore BlockingQueueCore.hh
 * 
 * 큐에 데이터가 있을 경우에 Queue 클래스와 같이 동작하지만, 큐가 비어있는 
 * 상태에서는 큐에 삽입(enqueue)이 있을 때 까지 대기한다.
 * 
 * 입력을 대기하기 위해서 - 즉, 데이터를 기다리는 스레드를 블럭킹 하기 위해서 -
 * 한 시그널(Signal)을 이용한다. 큐에 데이터가 입력되면 시그널을 발생시키고, 
 * 큐에서 데이터를 출력하면 시그널을 소비한다.
 * 
 * 또  Queue 클래스와 다른 점은 큐를 비울 때 - flush 메소드 호출 시 - 데이터 
 * 입력을 기다리는 스레드를 해방시켜 줘야 한다.
 * 
 * 마지막으로 Queue 클래스에 없는 인터페이스를 - release, setWaitingTime 
 * 메소드 - 지닌다. 이 인터페이스는 입력을 대기하는 스레드를 해방 시켜주거나
 * 최대 대기 시간을 결정하는데 사용한다.
 * 
 * \warning
 * 
 * 출력은 - dequeue 메소드 - 항상 데이터를 반환하지 않는다. 타임 아웃 
 * 되거나 release 메소드가 호출되는 경우에는 NULL을 반환한다.
 */
class BlockingQueueCore : public Queue
{
public:
	/**
	 * \name BlockingQueueCore
	 * \param AssignedSignal 입력이 도착 했을 때를 알리는 시그널.
	 */
	BlockingQueueCore(Signal* AssignedSignal);
	
	/**
	 * \name enqueue
	 * \param Object 삽입되는 오브젝트.
	 * 
	 * 큐에 데이터를 삽입한다.
	 * 
	 * 리스트(ListOfObject)에 데이터를 삽입하고, 시그널을 발생시킨다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf enqueue(void* Object);
	
	/**
	 * \name dequeue
	 * 
	 * 큐에서 데이터를 반환한다.
	 * 
	 * \return 
	 * 
	 * 리스트(ListOfObject)에 가장 오래된 오브젝트를 반환한다.
	 * 만약, 대기 시간을 초과하거나 release 메소드가 호출되는 경우에는 NULL을 
	 * 반환한다.
	 */
	virtual void* dequeue();
	
	/**
	 * \name dequeue
	 * \param ReturnedObject 리스트(ListOfObject)에 가장 오래된 오브젝트.
	 * 
	 * 큐에서 데이터를 반환한다.
	 * 
	 * 시그널을 기다리고, 큐에서 오브젝트를 빼온다.
	 * 만약, release 메소드나 대기시간을 초과한 경우에는 ReturnedObject는 
	 * NULL이 된다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf dequeue(void** ReturnedObject);
	
	/**
	 * \name fill
	 * 
	 * 큐에 삽입이 가능하도록 만든다.
	 * 
	 * flush 메소드는 큐를 비우기위해서 enqueue를 불가능하도록 한다.
	 * 다시 enqueue를 하기 위해서 fill 메소드를 사용한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf fill();
	
	/**
	 * \name flush
	 * 
	 * 큐를 비운다.
	 * 
	 * 큐에 새로운 데이터를 삽입하는 것을 불가능하게 한 후에 큐의 크기가 0이면 
	 * 바로 종료하고,큐의 크기가 0보다 클 경우에 큐가 비워졌다는 신호를 기다린다.
	 * 
	 * \warning
	 * 
	 * 큐가 비워질 때까지 새로운 데이터가 입력되는 것이 불가능해 진다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf flush();
	
	/**
	 * \name release
	 * 
	 * 대기하고 있는 스레드를 풀어 준다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf release();
	
	/**
	 * \name tellNumOfBlocking
	 * 
	 * 블럭킹된 스레드 개수를 알려준다.
	 * 
	 * \return 
	 * 
	 * 블럭킹된 스레드 개수.
	 */
	virtual Number tellNumOfBlocking();
	
	// Member
protected:
	/**
	 * 새로운 데이터가 도착하였을 알리는 시그널.
	 */
	Signal* SignalOfInputEvent;
};

#endif //BLOCKING_QUEUE_CORE_H_